import 'dart:io';
import 'dart:convert' as Convert;
import 'package:flutter/material.dart';

/// 豆瓣正在热映的电影
/// 1 网络请求 使用 http
/// 2 下拉刷新 使用 RefreshIndicator（包裹List即可，onRefresh是下拉刷新触发的时间监听）
/// 3 上拉加载 使用 ScrollController (添加 listener)

class DouBanMoviePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return DouBanMoviePageState();
  }
}

class DouBanMoviePageState extends State<DouBanMoviePage>
    with AutomaticKeepAliveClientMixin {
  var subjects = [];
  var itemHeight = 150.0;
  var _page = 1;
  var _hasReachedMax = false;
  ScrollController _scrollController = ScrollController();

  requestMovieTop(start) async {
    setState(() {
      _page = start;
    });
    var httpClient = new HttpClient();
    // https://douban.uieee.com/v2/movie/top250?start=25&count=10
    var uri = new Uri.https('douban.uieee.com', '/v2/movie/top250',
        {'start': start.toString(), 'count': '10'});
    var request = await httpClient.getUrl(uri);
    var response = await request.close();
    var responseBody = await response.transform(Convert.utf8.decoder).join();
    Map data = Convert.jsonDecode(responseBody);
    setState(() {
      subjects += data['subjects'];
      _hasReachedMax = subjects.length >= 250;
    });
  }

  @override
  void initState() {
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        _loadMoreData();
        print('_loadMoreData 开始执行');
      }
    });
    super.initState();
    _loadNewData();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('电影Top200')), body: getListViewContainer());
  }

  getListViewContainer() {
    var count = subjects.length;
    if (count == 0) {
      //loading
      return Center(
        child: CircularProgressIndicator(),
      );
    }
    return RefreshIndicator(
        onRefresh: _loadNewData,
        child: ListView.builder(
            controller: _scrollController,
            //item 的数量
            itemCount: _hasReachedMax ? count : count + 1,
            itemBuilder: (BuildContext context, int index) {
              if (index >= count) {
                return BottomLoader();
              }
              return GestureDetector(
                //Flutter 手势处理
                child: Container(
                  color: Colors.transparent,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      numberWidget(index + 1),
                      getItemContainerView(subjects[index]),
                      //下面的灰色分割线
                      Container(
                        height: 10,
                        color: Color.fromARGB(255, 234, 233, 234),
                      )
                    ],
                  ),
                ),
                onTap: () {
                  //监听点击事件
                  print("click item index=$index");
                  // TODO 新路由
//                  router.push(context,
//                      name: 'other_movie_detail',
//                      query: {'subject': subjects[index]});
                },
              );
            }));
  }

  Future<void> _loadNewData() async {
    setState(() {
      subjects = [];
    });
    await requestMovieTop(1);
    return Null;
  }

  Future<void> _loadMoreData() async {
    await requestMovieTop(_page + 1);
    return Null;
  }

  //肖申克的救赎(1993) View
  getTitleView(subject) {
    var title = subject['title'];
    var year = subject['year'];
    return Container(
      child: Row(
        children: <Widget>[
          Icon(
            Icons.play_circle_outline,
            color: Colors.redAccent,
          ),
          Text(
            title,
            style: TextStyle(
                fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black),
          ),
          Text('($year)',
              style: TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.bold,
                  color: Colors.grey))
        ],
      ),
    );
  }

  getItemContainerView(var subject) {
    var imgUrl = subject['images']['medium'];
    return Container(
      width: double.infinity,
      padding: EdgeInsets.all(5.0),
      child: Row(
        children: <Widget>[
          getImage(imgUrl),
          Expanded(
            child: getMovieInfoView(subject),
            flex: 1,
          )
        ],
      ),
    );
  }

  //圆角图片
  getImage(var imgUrl) {
    return Container(
      decoration: BoxDecoration(
          image:
              DecorationImage(image: NetworkImage(imgUrl), fit: BoxFit.cover),
          borderRadius: BorderRadius.all(Radius.circular(5.0))),
      margin: EdgeInsets.only(left: 8, top: 3, right: 8, bottom: 3),
      height: itemHeight,
      width: 100.0,
    );
  }

  getStaring(var stars) {
    return Row(
      children: <Widget>[RatingBar(stars), Text('$stars')],
    );
  }

  //电影标题，星标评分，演员简介Container
  getMovieInfoView(var subject) {
    var start = subject['rating']['average'];
    return Container(
      height: itemHeight,
      alignment: Alignment.topLeft,
      child: Column(
        children: <Widget>[
          getTitleView(subject),
          RatingBar(start),
          DescWidget(subject)
        ],
      ),
    );
  }

  //NO.1 图标
  numberWidget(var no) {
    return Container(
      child: Text(
        'No.$no',
        style: TextStyle(color: Color.fromARGB(255, 133, 66, 0)),
      ),
      decoration: BoxDecoration(
          color: Color.fromARGB(255, 255, 201, 129),
          borderRadius: BorderRadius.all(Radius.circular(5.0))),
      padding: EdgeInsets.fromLTRB(8, 4, 8, 4),
      margin: EdgeInsets.only(left: 12, top: 10),
    );
  }

//
//  Flutter中为了节约内存不会保存widget的状态，widget都是临时变量。当我们使用TabBar，TabBarView是我们就会发现，切换tab后再重新切换回上一页面，这时候tab会重新加载重新创建，体验很不友好。Flutter出于自己的设计考虑并没有延续android的ViewPager这样的缓存页面设计，毕竟控件两端都要开发，目前还在beta版本有很多设计还不够完善，但是设计的拓展性没得说，flutter还是为我们提供了解决办法。我们可以强制widget不显示情况下保留状态，下回再加载时就不用重新创建了。
//
//  AutomaticKeepAliveClientMixin
//  AutomaticKeepAliveClientMixin 是一个抽象状态，使用也很简单，我们只需要用我们自己的状态继承这个抽象状态，并实现 wantKeepAlive 方法即可。
//
//  继承这个状态后，widget在不显示之后也不会被销毁仍然保存在内存中，所以慎重使用这个方法。
//  原文：https://blog.csdn.net/tgbus18990140382/article/details/81181879

  @override
  bool get wantKeepAlive => true;
}

//类别、演员介绍
class DescWidget extends StatelessWidget {
  var subject;

  DescWidget(this.subject);

  @override
  Widget build(BuildContext context) {
    var casts = subject['casts'];
    var sb = StringBuffer();
    var genres = subject['genres'];
    for (var i = 0; i < genres.length; i++) {
      sb.write('${genres[i]}  ');
    }
    sb.write("/ ");
    List<String> list = List.generate(
        casts.length, (int index) => casts[index]['name'].toString());

    for (var i = 0; i < list.length; i++) {
      sb.write('${list[i]} ');
    }
    return Container(
      alignment: Alignment.topLeft,
      child: Text(
        sb.toString(),
        softWrap: true,
        textDirection: TextDirection.ltr,
        style:
            TextStyle(fontSize: 16, color: Color.fromARGB(255, 118, 117, 118)),
      ),
    );
  }
}

class RatingBar extends StatelessWidget {
  double stars;

  RatingBar(this.stars);

  @override
  Widget build(BuildContext context) {
    List<Widget> startList = [];
    //实心星星
    var startNumber = stars ~/ 2;
    //半实心星星
    var startHalf = 0;
    if (stars.toString().contains('.')) {
      int tmp = int.parse((stars.toString().split('.')[1]));
      if (tmp >= 5) {
        startHalf = 1;
      }
    }
    //空心星星
    var startEmpty = 5 - startNumber - startHalf;

    for (var i = 0; i < startNumber; i++) {
      startList.add(Icon(
        Icons.star,
        color: Colors.amberAccent,
        size: 18,
      ));
    }
    if (startHalf > 0) {
      startList.add(Icon(
        Icons.star_half,
        color: Colors.amberAccent,
        size: 18,
      ));
    }
    for (var i = 0; i < startEmpty; i++) {
      startList.add(Icon(
        Icons.star_border,
        color: Colors.grey,
        size: 18,
      ));
    }
    startList.add(Text(
      '$stars',
      style: TextStyle(
        color: Colors.grey,
      ),
    ));
    return Container(
      alignment: Alignment.topLeft,
      padding: const EdgeInsets.only(left: 0, top: 8, right: 0, bottom: 5),
      child: Row(
        children: startList,
      ),
    );
  }
}

class BottomLoader extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
        alignment: Alignment.center,
        child: Padding(
          padding: EdgeInsets.symmetric(vertical: 10.0),
          child: Center(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  SizedBox(
                    width: 33,
                    height: 33,
                    child: CircularProgressIndicator(strokeWidth: 1.5),
              ),
              Text('正在加载...')
            ],
          )),
        ));
  }
}
